package com.wxapp.common.util.menuTree;
import com.wxapp.common.constant.base.IBaseTreeEntity;
import com.wxapp.common.constant.base.IBaseTree;
import com.wxapp.common.util.check.CheckUtil;
import com.wxapp.common.util.copy.CallBack;
import com.wxapp.common.util.copy.CopyUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

public class TreeUtil {

    private TreeUtil(){}
    //建立树形结构
    public static <T extends IBaseTree<T>, S extends IBaseTreeEntity> List<T> buildCopyTree(List<S> detailDOS, Supplier<T> target, CallBack<S, T> callBack) {
        List<T> treeMenus = new ArrayList<>();
        if (CheckUtil.isNotNullList(detailDOS)) {
            List<S> rootNode = getCopyRootNode(detailDOS);
            if (CheckUtil.isNotNullList(rootNode)) {
                rootNode.forEach(s -> {
                    T childTree = buildCopyChildTree(s, detailDOS, target, callBack);
                    treeMenus.add(childTree);
                });
            } else {
                return CopyUtil.copyListNew(detailDOS, target, callBack);
            }
        }
        return treeMenus;
    }

    //建立树形结构
    public static <T extends IBaseTree<T>> List<T> buildTree(List<T> detailDOS, com.wxapp.common.util.menuTree.CallBack<T> callBack) {
        List<T> treeMenus = new ArrayList<>();
        if (CheckUtil.isNotNullList(detailDOS)) {
            List<T> rootNode = getRootNode(detailDOS);
            if (CheckUtil.isNotNullList(rootNode)) {
                rootNode.forEach(s -> {
                    buildChildTree(s, detailDOS,callBack);
                    callBack.callBack(s);
                    treeMenus.add(s);
                });
            } else {
                return detailDOS;
            }
        }
        return treeMenus;
    }

    /**
     *将树状结构转换为平铺数据结构(将含有children的树状结构转换为仅有节点和父节点的对象列表)
     *
     * @param detailDOS 树状结构数据列表
     * @param <T>       任意类型参数
     * @return 平铺数据结构列表
     */
    public static <T extends IBaseTree<T>> List<T> convertToObjList(List<T> detailDOS) {

        List<T> treeMenus = new ArrayList<>();
        for (T menuNode : detailDOS) {
            if (menuNode.getChildren() != null) {
                treeMenus.add(menuNode);
                convertToObjList(menuNode.getChildren(), treeMenus);
            } else {
                treeMenus.add(menuNode);
            }
        }
        return treeMenus;
    }

    private static <T extends IBaseTree<T>> void convertToObjList(List<T> source, List<T> outList) {
        if (outList == null) {
            outList = new ArrayList<>();
        }
        for (T tTreeStructure : source) {
            if (tTreeStructure.getChildren() != null) {
                outList.add(tTreeStructure);
                convertToObjList(tTreeStructure.getChildren(), outList);
            } else {
                outList.add(tTreeStructure);
            }
        }
    }

    //获取根节点
    private static <S extends IBaseTreeEntity> List<S> getCopyRootNode(List<S> detailDOS) {
        List<S> rootMenuLists = new ArrayList<>();
        detailDOS.parallelStream().forEach(s -> {
            if (CheckUtil.isNullString(s.getPid()) || "0".equals(s.getPid())) {
                rootMenuLists.add(s);
            }
        });
        return rootMenuLists;
    }

    //获取根节点
    private static <T extends IBaseTree<T>> List<T> getRootNode(List<T> detailDOS) {
        List<T> rootMenuLists = new ArrayList<>();
        detailDOS.forEach(menuNode -> {
            if (CheckUtil.isNullString(menuNode.getPid()) || "0".equals(menuNode.getPid())) {
                rootMenuLists.add(menuNode);
            }
        });
        return rootMenuLists;
    }

    //递归，建立子树形结构
    private static <T extends IBaseTree<T>, S extends IBaseTreeEntity> T buildCopyChildTree(S pNode, List<S> detailDOS, Supplier<T> supplier, CallBack<S, T> callBack) {
        List<T> childMenus = new ArrayList<>();
        detailDOS.forEach(s -> {
            if (CheckUtil.isNotNullString(s.getPid()) && CheckUtil.isNotNullString(pNode.getId()) && s.getPid().equals(pNode.getId())) {
                childMenus.add(buildCopyChildTree(s, detailDOS, supplier, callBack));
            }
        });
        var aNew = CopyUtil.copyObjectNew(pNode, supplier, callBack);
        if (CheckUtil.isNotNullList(childMenus)) {
            aNew.setChildren(childMenus);
        }
        return aNew;
    }

    //递归，建立子树形结构
    private static <T extends IBaseTree<T>> T buildChildTree(T pNode, List<T> detailDOS, com.wxapp.common.util.menuTree.CallBack<T> callBack) {
        List<T> childMenus = new ArrayList<>();
        for (T menuNode : detailDOS) {
            if (CheckUtil.isNotNullString(menuNode.getPid()) && CheckUtil.isNotNullString(pNode.getId()) && menuNode.getPid().equals(pNode.getId())) {
                callBack.callBack(menuNode);
                childMenus.add(buildChildTree(menuNode, detailDOS,callBack));
            }
        }
        if (CheckUtil.isNotNullList(childMenus)) {
            pNode.setChildren(childMenus);
        }
        return pNode;
    }
}